package com.nineclock.attendance.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.attendance.dto.AttendGroupDTO;
import com.nineclock.attendance.dto.AttendGroupPCExtraConfigDTO;
import com.nineclock.attendance.dto.AttendGroupPartDTO;
import com.nineclock.attendance.enums.AttendEnums;
import com.nineclock.attendance.mapper.AttendGroupMapper;
import com.nineclock.attendance.mapper.AttendGroupPartMapper;
import com.nineclock.attendance.pojo.AttendGroup;
import com.nineclock.attendance.pojo.AttendGroupPart;
import com.nineclock.attendance.service.AttendGroupService;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.feign.SysCompanyUserFeign;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class AttendGroupServiceImpl implements AttendGroupService {
    @Autowired
    private AttendGroupMapper attendGroupMapper;
    @Autowired
    private SysCompanyUserFeign companyUserFeign;
    @Autowired
    private AttendGroupPartMapper attendGroupPartMapper;

    private AttendGroup createDefaultAttendGroup() {
        AttendGroup attendGroup = new AttendGroup();
        attendGroup.setName("默认考勤组");
        attendGroup.setCompanyId(CurrentUserHolder.get().getCompanyId());
        attendGroup.setStartWorkTime("9:00:00");
        attendGroup.setAllowLateMinutes(10);
        attendGroup.setLateMinutes(30);
        attendGroup.setStartNoonRestTime("12:00:00");
        attendGroup.setEndNoonRestTime("14:00:00");
        attendGroup.setOffWorkTime("18:00:00");
        attendGroup.setWorkdays("1,1,1,1,1,0,0");
        attendGroup.setAddress("广东省广州市天河区珠吉街道珠吉路58号黑马培训机构");
        attendGroup.setAddressName("广州黑马程序员");
        attendGroup.setLng(new BigDecimal("23.13514700000000000000"));
        attendGroup.setLat(new BigDecimal("113.43467700000000000000"));
        attendGroup.setAddressRange(500);
        attendGroup.setCreateUserId(CurrentUserHolder.get().getCompanyUserId());
        attendGroup.setCreateTime(new Date());
        attendGroup.setUpdateTime(new Date());
        attendGroup.setUpdateUserId(CurrentUserHolder.get().getCompanyUserId());
        return attendGroup;
    }

    @Override
    public PageResult<AttendGroupDTO> getAttendGroupPage(Integer page, Integer pageSize) {
        //1. 查询当前企业是否初次使用
        LambdaQueryWrapper<AttendGroup> wrapperFirst = new LambdaQueryWrapper<>();
        wrapperFirst.eq(AttendGroup::getCompanyId, CurrentUserHolder.get().getCompanyId());
        Integer count = attendGroupMapper.selectCount(wrapperFirst);
        if (count == 0) {
            //2. 如果初次使用需要新增默认考勤组, 设置企业所有部门员工都采用默认考勤组 (调用系统微服务获取企业所有部门)
            AttendGroup attendGroup = this.createDefaultAttendGroup();
            attendGroupMapper.insert(attendGroup);
            List<Long> departmentIdList = companyUserFeign.getAllDepartmentId().getData();
            if (!CollectionUtils.isEmpty(departmentIdList)) {
                for (Long departmentId : departmentIdList) {
                    AttendGroupPart attendGroupPart = new AttendGroupPart();
                    attendGroupPart.setAttendGroupId(attendGroup.getId());
                    attendGroupPart.setObjectType(AttendEnums.ATTEND_OBJECT_TYPE_DEP.value());
                    attendGroupPart.setObjectId(departmentId);
                    attendGroupPart.setAttendType(AttendEnums.ATTEND_TYPE_YES.value());
                    attendGroupPartMapper.insert(attendGroupPart);
                }
            }

        }
        //3. 分页查询企业考勤组列表数据
        IPage<AttendGroup> ipage = new Page<>(page, pageSize);
        ipage = attendGroupMapper.selectPage(ipage, wrapperFirst);
        //4. 遍历列表，获取企业考勤组中参与者数量
        List<AttendGroup> AttendGroups = ipage.getRecords();
        List<AttendGroupDTO> attendGroupDTOList = BeanHelper.copyWithCollection(AttendGroups, AttendGroupDTO.class);

        for (AttendGroupDTO attendGroupDTO : attendGroupDTOList) {

            LambdaQueryWrapper<AttendGroupPart> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AttendGroupPart::getAttendGroupId, attendGroupDTO.getId());
            wrapper.eq(AttendGroupPart::getAttendType, AttendEnums.ATTEND_TYPE_YES.value());
            List<AttendGroupPart> attendGroupPartList = attendGroupPartMapper.selectList(wrapper);
            if (!CollectionUtils.isEmpty(attendGroupPartList)) {
                Integer sum = 0;
                List<Long> departmentIdList = new ArrayList<>();
                for (AttendGroupPart attendGroupPart : attendGroupPartList) {
                    if (attendGroupPart.getObjectType() == AttendEnums.ATTEND_OBJECT_TYPE_USER.value()) {
                        sum++;
                    } else {
                        departmentIdList.add(attendGroupPart.getObjectId());
                    }
                }
                //考勤part表中的部门和用户id查出来了后通过部门id查
                if (departmentIdList.size() > 0) {
                    Integer data = companyUserFeign.getAllUserByDepartmentIdList(departmentIdList).getData();
                    if (data != null) {
                        sum = sum + data;
                    }
                }

                attendGroupDTO.setMemberNum(sum);
            }
        }
        return new PageResult<>(ipage.getTotal(), ipage.getPages(), attendGroupDTOList);
    }

    @Override
    public void insertAttendGroup(AttendGroupDTO attendGroupDTO) {
        if (attendGroupDTO == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        AttendGroup attendGroup = BeanHelper.copyProperties(attendGroupDTO, AttendGroup.class);
        attendGroup.setCompanyId(CurrentUserHolder.get().getCompanyId());
        attendGroup.setCreateUserId(CurrentUserHolder.get().getCompanyUserId());
        attendGroup.setUpdateUserId(CurrentUserHolder.get().getCompanyUserId());

        //工作日 1,1,1,1,1,0,0
        if (attendGroupDTO.getWorkdays() != null){
            attendGroup.setWorkdays(StrUtil.join(",",attendGroupDTO.getWorkdays().toArray()));
        }
        List<String> necessaryTimeList = new ArrayList<>();
        List<String> unnecessaryTimeList = new ArrayList<>();
        List<AttendGroupPCExtraConfigDTO> extraConfigList = attendGroupDTO.getExtraConfig();
        for (AttendGroupPCExtraConfigDTO extraConfigDTO : extraConfigList) {
            String time = extraConfigDTO.getSetDate();
            String date = DateUtil.format(new Date(Long.valueOf(time)), "yyyy-MM-dd");
            if (extraConfigDTO.getRequiredAttend() == 1){
                necessaryTimeList.add(date);
            }else {
                unnecessaryTimeList.add(date);
            }
        }
        attendGroup.setNecessaryTimeList(StrUtil.join(",", necessaryTimeList.toArray()));
        attendGroup.setUnnecessaryTimeList(StrUtil.join(",",unnecessaryTimeList.toArray()));
        attendGroupMapper.insert(attendGroup);
        this.saveAttendGroupPart(attendGroupDTO,attendGroup);
    }

    @Override
    public AttendGroupDTO getAttendGroupByUserId() {
        Long companyUserId = CurrentUserHolder.get().getCompanyUserId();
        LambdaQueryWrapper<AttendGroupPart> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AttendGroupPart::getObjectId,companyUserId);
        wrapper.eq(AttendGroupPart::getObjectType,AttendEnums.ATTEND_OBJECT_TYPE_USER.value());
        wrapper.eq(AttendGroupPart::getAttendType,AttendEnums.ATTEND_TYPE_YES.value());
        AttendGroupPart attendGroupPart = attendGroupPartMapper.selectOne(wrapper);
        if (attendGroupPart == null){
            List<Long> idList = companyUserFeign.getAllDepIdByCompanyUserId(companyUserId).getData();
            for (Long departmentId : idList) {
                LambdaQueryWrapper<AttendGroupPart> wrapperDep = new LambdaQueryWrapper<>();
                wrapperDep.eq(AttendGroupPart::getObjectType,AttendEnums.ATTEND_OBJECT_TYPE_DEP.value());
                wrapperDep.eq(AttendGroupPart::getObjectId,departmentId);
                wrapperDep.eq(AttendGroupPart::getAttendType,AttendEnums.ATTEND_TYPE_YES.value());
                 attendGroupPart = attendGroupPartMapper.selectOne(wrapperDep);
                if (attendGroupPart != null){
                    break;
                }
            }

        }
        if (attendGroupPart == null){
            throw new NcException(ResponseEnum.USER_NOT_MATCH_ATTENDGROUP);
        }else {
            AttendGroup attendGroup = attendGroupMapper.selectById(attendGroupPart.getAttendGroupId());
            AttendGroupDTO attendGroupDTO = BeanHelper.copyProperties(attendGroup, AttendGroupDTO.class);
            String workdays = attendGroup.getWorkdays();
            attendGroupDTO.setWorkdays(Arrays.asList(workdays.split(",")));
            return attendGroupDTO;
        }
    }

    private void saveAttendGroupPart(AttendGroupDTO attendGroupDTO,AttendGroup attendGroup) {
        List<AttendGroupPartDTO> participates = attendGroupDTO.getParticipates();
        List<AttendGroupPartDTO> notParticipates = attendGroupDTO.getNotParticipates();
        if (!CollectionUtils.isEmpty(participates)){
            for (AttendGroupPartDTO participate : participates) {
                LambdaQueryWrapper<AttendGroupPart> wrapperY = new LambdaQueryWrapper<>();
                wrapperY.eq(AttendGroupPart::getObjectId,participate.getObjectId());
                wrapperY.eq(AttendGroupPart::getObjectType,participate.getObjectType());
                wrapperY.eq(AttendGroupPart::getAttendType,AttendEnums.ATTEND_TYPE_YES.value());
                Integer count = attendGroupPartMapper.selectCount(wrapperY);
                if (count > 0){
                    attendGroupPartMapper.delete(wrapperY);
                }else {
                    AttendGroupPart groupPart = new AttendGroupPart();
                    groupPart.setAttendGroupId(attendGroup.getId());
                    groupPart.setObjectType(participate.getObjectType());
                    groupPart.setObjectId(participate.getObjectId());
                    groupPart.setAttendType(AttendEnums.ATTEND_TYPE_YES.value());
                    attendGroupPartMapper.insert(groupPart);
                }
            }
        }
        if (!CollectionUtils.isEmpty(notParticipates)){
            for (AttendGroupPartDTO notParticipate : notParticipates) {
                LambdaQueryWrapper<AttendGroupPart> wrapperN = new LambdaQueryWrapper<>();
                wrapperN.eq(AttendGroupPart::getObjectId,notParticipate.getObjectId());
                wrapperN.eq(AttendGroupPart::getObjectType,notParticipate.getObjectType());
                wrapperN.eq(AttendGroupPart::getAttendType,AttendEnums.ATTEND_TYPE_NO.value());
                Integer count = attendGroupPartMapper.selectCount(wrapperN);
                if (count == 0){
                    AttendGroupPart groupPart = new AttendGroupPart();
                    groupPart.setAttendGroupId(attendGroup.getId());
                    groupPart.setObjectType(notParticipate.getObjectType());
                    groupPart.setObjectId(notParticipate.getObjectId());
                    groupPart.setAttendType(AttendEnums.ATTEND_TYPE_NO.value());
                    attendGroupPartMapper.insert(groupPart);
                }
            }
        }
    }


}
